package com.lwl.java.base;

import java.util.Random;
import java.util.concurrent.*;

/**
 * @author lwl
 * @Description TODO
 * @date 2025/9/6 15:26
 */
public class BlockingQueueDemo {


    // 使用有界阻塞队列防止内存溢出，假设最大积压订单量为100
    private static final BlockingQueue<Order> orderQueue = new LinkedBlockingQueue<>(100);
    private static final Random random = new Random();
    private static volatile boolean isRunning = true; // 系统运行标志

    public static void main(String[] args) throws InterruptedException {
        // 使用线程池管理订单处理员（消费者）
        ExecutorService consumerPool = Executors.newFixedThreadPool(3); // 3个订单处理员

        // 启动订单生成器（生产者）
        Thread producerThread = new Thread(new OrderProducer(), "Order-Producer");
        producerThread.start();

        // 启动3个订单处理员（消费者）
        for (int i = 1; i <= 3; i++) {
            consumerPool.execute(new OrderConsumer("Order-Processor-" + i));
        }

        // 让系统运行一段时间
        TimeUnit.SECONDS.sleep(10);

        // 优雅关闭系统
        isRunning = false;
        producerThread.interrupt(); // 中断生产者
        consumerPool.shutdown(); // 关闭消费者线程池
        if (!consumerPool.awaitTermination(5, TimeUnit.SECONDS)) {
            consumerPool.shutdownNow(); // 强制关闭
        }
        System.out.println("系统已关闭。");
    }

    // 订单类
    static class Order {
        private final String orderId;
        private final String product;
        private final int quantity;

        public Order(String orderId, String product, int quantity) {
            this.orderId = orderId;
            this.product = product;
            this.quantity = quantity;
        }

        @Override
        public String toString() {
            return "Order{id='" + orderId + "', product='" + product + "', quantity=" + quantity + "}";
        }
    }

    // 生产者 - 订单生成器
    static class OrderProducer implements Runnable {
        private int orderCount = 0;

        @Override
        public void run() {
            try {
                while (isRunning && !Thread.currentThread().isInterrupted()) {
                    // 模拟生成订单的耗时
                    TimeUnit.MILLISECONDS.sleep(200 + random.nextInt(300));
                    String orderId = "ORD-" + (++orderCount);
                    String[] products = {"Phone", "Laptop", "Tablet", "Headphones"};
                    String product = products[random.nextInt(products.length)];
                    int quantity = 1 + random.nextInt(3);
                    Order newOrder = new Order(orderId, product, quantity);

                    // 将订单放入队列。若队列满，此方法会阻塞，直到有空间可用。
                    orderQueue.put(newOrder);
                    System.out.println(Thread.currentThread().getName() + " 生成: " + newOrder);
                }
            } catch (InterruptedException e) {
                // 响应中断，优雅退出
                Thread.currentThread().interrupt();
                System.out.println(Thread.currentThread().getName() + " 被中断，停止生成订单。");
            }
            System.out.println(Thread.currentThread().getName() + " 结束运行。");
        }
    }

    // 消费者 - 订单处理员
    static class OrderConsumer implements Runnable {
        private final String processorName;

        public OrderConsumer(String name) {
            this.processorName = name;
        }

        @Override
        public void run() {
            try {
                while (isRunning) { // 系统在运行或队列还有订单
                    // 从队列中取出订单进行处理。若队列空，此方法会阻塞，直到有新订单。
                    Order orderToProcess = orderQueue.poll(1, TimeUnit.SECONDS); // 轮询时设置超时，便于检查系统状态

                    if (orderToProcess != null) {
                        System.out.println(processorName + " 开始处理: " + orderToProcess);
                        // 模拟处理订单的耗时（比生成慢）
                        TimeUnit.MILLISECONDS.sleep(500 + random.nextInt(600));
                        System.out.println(processorName + " 完成处理: " + orderToProcess);
                    }
                }
            } catch (InterruptedException e) {
                // 响应中断，优雅退出
                Thread.currentThread().interrupt();
                System.out.println(processorName + " 被中断。");
            }
            System.out.println(processorName + " 结束运行。");
        }
    }
}
